/*      */ package com.zimbra.cs.session;
/*      */ 
/*      */ import com.google.common.io.Closeables;
/*      */ import com.zimbra.common.account.Key.AccountBy;
/*      */ import com.zimbra.common.localconfig.DebugConfig;
/*      */ import com.zimbra.common.localconfig.KnownKey;
/*      */ import com.zimbra.common.localconfig.LC;
/*      */ import com.zimbra.common.service.ServiceException;
/*      */ import com.zimbra.common.soap.Element;
/*      */ import com.zimbra.common.soap.Element.Disposition;
/*      */ import com.zimbra.common.soap.Element.ElementFactory;
/*      */ import com.zimbra.common.soap.MailConstants;
/*      */ import com.zimbra.common.soap.SoapProtocol;
/*      */ import com.zimbra.common.util.Log;
/*      */ import com.zimbra.common.util.Pair;
/*      */ import com.zimbra.common.util.StringUtil;
/*      */ import com.zimbra.common.util.ZimbraLog;
/*      */ import com.zimbra.cs.account.AccessManager;
/*      */ import com.zimbra.cs.account.Account;
/*      */ import com.zimbra.cs.account.Provisioning;
/*      */ import com.zimbra.cs.account.Server;
/*      */ import com.zimbra.cs.httpclient.URLUtil;
/*      */ import com.zimbra.cs.index.ZimbraQueryResults;
/*      */ import com.zimbra.cs.mailbox.Comment;
/*      */ import com.zimbra.cs.mailbox.Conversation;
/*      */ import com.zimbra.cs.mailbox.Flag;
/*      */ import com.zimbra.cs.mailbox.Folder;
/*      */ import com.zimbra.cs.mailbox.MailItem;
/*      */ import com.zimbra.cs.mailbox.MailItem.Type;
/*      */ import com.zimbra.cs.mailbox.Mailbox;
/*      */ import com.zimbra.cs.mailbox.Mailbox.FolderNode;
/*      */ import com.zimbra.cs.mailbox.MailboxLock;
/*      */ import com.zimbra.cs.mailbox.MailboxManager;
/*      */ import com.zimbra.cs.mailbox.Message;
/*      */ import com.zimbra.cs.mailbox.Mountpoint;
/*      */ import com.zimbra.cs.mailbox.OperationContext;
/*      */ import com.zimbra.cs.mailbox.OperationContextData;
/*      */ import com.zimbra.cs.mailbox.Tag;
/*      */ import com.zimbra.cs.service.mail.GetFolder;
/*      */ import com.zimbra.cs.service.mail.ToXML;
/*      */ import com.zimbra.cs.service.util.ItemId;
/*      */ import com.zimbra.cs.service.util.ItemIdFormatter;
/*      */ import com.zimbra.cs.util.BuildInfo;
/*      */ import com.zimbra.cs.util.Zimbra;
/*      */ import com.zimbra.soap.DocumentHandler;
/*      */ import com.zimbra.soap.ProxyTarget;
/*      */ import com.zimbra.soap.ZimbraSoapContext;
/*      */ import java.util.ArrayList;
/*      */ import java.util.Collection;
/*      */ import java.util.Collections;
/*      */ import java.util.HashMap;
/*      */ import java.util.Iterator;
/*      */ import java.util.LinkedHashMap;
/*      */ import java.util.LinkedList;
/*      */ import java.util.List;
/*      */ import java.util.Map;
/*      */ import java.util.Map.Entry;
/*      */ import java.util.Set;
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ public class SoapSession
/*      */   extends Session
/*      */ {
/*      */   public class DelegateSession
/*      */     extends Session
/*      */   {
/*      */     private long mNextFolderCheck;
/*      */     private Set<Integer> mVisibleFolderIds;
/*   83 */     private boolean mParentHasFullAccess = false;
/*      */     private static final int BASIC_CONVERSATION_FLAGS = 7;
/*      */     
/*   86 */     DelegateSession(String authId, String targetId) { super(targetId, Session.Type.SOAP); }
/*      */     
/*      */     public SoapSession getParentSession()
/*      */     {
/*   90 */       return SoapSession.this;
/*      */     }
/*      */     
/*      */     public DelegateSession register() {
/*      */       try {
/*   95 */         super.register();
/*   96 */         calculateVisibleFolders(true);
/*   97 */         return this;
/*      */       } catch (ServiceException e) {
/*   99 */         unregister(); }
/*  100 */       return null;
/*      */     }
/*      */     
/*      */     public DelegateSession unregister()
/*      */     {
/*  105 */       super.unregister();
/*  106 */       SoapSession.this.removeDelegateSession(this);
/*  107 */       return this;
/*      */     }
/*      */     
/*      */     protected boolean isMailboxListener() {
/*  111 */       return true;
/*      */     }
/*      */     
/*      */     protected boolean isRegisteredInCache() {
/*  115 */       return false;
/*      */     }
/*      */     
/*      */     protected long getSessionIdleLifetime() {
/*  119 */       return 2147483647L;
/*      */     }
/*      */     
/*      */     public void cleanup() {}
/*      */     
/*      */     public void notifyPendingChanges(PendingModifications pms, int changeId, Session source) {
/*      */       try {
/*  126 */         if (calculateVisibleFolders(false))
/*  127 */           pms = filterNotifications(pms);
/*  128 */         if ((pms != null) && (pms.hasNotifications()))
/*  129 */           SoapSession.this.handleNotifications(pms, (source == this) || (source == SoapSession.this));
/*      */       } catch (ServiceException e) {
/*  131 */         ZimbraLog.session.warn("exception during delegated notifyPendingChanges", e);
/*      */       }
/*      */     }
/*      */     
/*      */     public void notifyExternalEvent(Session.ExternalEventNotification extra) {
/*  136 */       Account authAccount = null;
/*      */       try {
/*  138 */         authAccount = Provisioning.getInstance().getAccountById(getAuthenticatedAccountId());
/*      */       }
/*      */       catch (ServiceException e) {}
/*  141 */       if (extra.canAccess(authAccount)) {
/*  142 */         SoapSession.this.notifyExternalEvent(extra);
/*      */       }
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */     protected boolean skipChangeSerialization(Mailbox mbox, MailItem item)
/*      */       throws ServiceException
/*      */     {
/*  152 */       return (mbox != item.getMailbox()) && ((item instanceof Conversation)) && (((Conversation)item).getMessageCount() > 50) && (!this.mParentHasFullAccess);
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*      */     private static final int MODIFIED_CONVERSATION_FLAGS = 2071;
/*      */     
/*      */     protected void cacheAccountAccess(String authedAcctId, String targetAcctId)
/*      */       throws ServiceException
/*      */     {
/*  162 */       Provisioning prov = Provisioning.getInstance();
/*  163 */       this.mParentHasFullAccess = AccessManager.getInstance().canAccessAccount(prov.get(Key.AccountBy.id, authedAcctId), prov.get(Key.AccountBy.id, targetAcctId), getParentSession().asAdmin());
/*      */     }
/*      */     
/*      */     private boolean calculateVisibleFolders(boolean force)
/*      */       throws ServiceException
/*      */     {
/*  169 */       long now = System.currentTimeMillis();
/*      */       
/*  171 */       Mailbox mbox = this.mailbox;
/*  172 */       cacheAccountAccess(this.mAuthenticatedAccountId, this.mTargetAccountId);
/*  173 */       if (mbox == null) {
/*  174 */         this.mVisibleFolderIds = Collections.emptySet();
/*  175 */         return true;
/*      */       }
/*      */       
/*  178 */       mbox.lock.lock();
/*      */       try {
/*  180 */         if ((!force) && ((this.mNextFolderCheck < 0L) || (this.mNextFolderCheck > now))) {
/*  181 */           return this.mVisibleFolderIds != null;
/*      */         }
/*      */         
/*  184 */         Object visible = MailItem.toId(mbox.getVisibleFolders(new OperationContext(getAuthenticatedAccountId())));
/*  185 */         this.mVisibleFolderIds = ((Set)visible);
/*  186 */         this.mNextFolderCheck = (DebugConfig.visibileFolderRecalcInterval > 0 ? now + DebugConfig.visibileFolderRecalcInterval : -1L);
/*  187 */         return visible != null;
/*      */       } finally {
/*  189 */         mbox.lock.release();
/*      */       }
/*      */     }
/*      */     
/*      */     private boolean folderRecalcRequired(PendingModifications pms) {
/*  194 */       boolean recalc = false;
/*  195 */       if ((pms.created != null) && (!pms.created.isEmpty())) {
/*  196 */         for (MailItem item : pms.created.values()) {
/*  197 */           if ((item instanceof Folder))
/*  198 */             return true;
/*      */         }
/*      */       }
/*  201 */       if ((!recalc) && (pms.modified != null) && (!pms.modified.isEmpty())) {
/*  202 */         for (PendingModifications.Change chg : pms.modified.values()) {
/*  203 */           if (((chg.why & 0x200100) != 0) && ((chg.what instanceof Folder))) {
/*  204 */             return true;
/*      */           }
/*      */         }
/*      */       }
/*  208 */       return false;
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*      */     private PendingModifications filterNotifications(PendingModifications pms)
/*      */       throws ServiceException
/*      */     {
/*  216 */       if ((folderRecalcRequired(pms)) && (!calculateVisibleFolders(true))) {
/*  217 */         return pms;
/*      */       }
/*  219 */       Set<Integer> visible = this.mVisibleFolderIds;
/*  220 */       if (visible == null) {
/*  221 */         return pms;
/*      */       }
/*      */       
/*  224 */       OperationContext octxt = new OperationContext(getAuthenticatedAccountId());
/*  225 */       PendingModifications filtered = new PendingModifications();
/*  226 */       filtered.changedTypes = pms.changedTypes;
/*  227 */       if ((pms.deleted != null) && (!pms.deleted.isEmpty())) {
/*  228 */         filtered.recordDeleted(pms.deleted);
/*      */       }
/*  230 */       if ((pms.created != null) && (!pms.created.isEmpty())) {
/*  231 */         for (MailItem item : pms.created.values()) {
/*  232 */           if (!(item instanceof Conversation)) { if (!visible.contains(Integer.valueOf((item instanceof Folder) ? item.getId() : item.getFolderId()))) {}
/*      */           } else {
/*  234 */             filtered.recordCreated(item);
/*  235 */             break label228; } if ((item instanceof Comment)) {
/*      */             try {
/*  237 */               this.mailbox.getItemById(octxt, item.getParentId(), MailItem.Type.UNKNOWN);
/*  238 */               filtered.recordCreated(item);
/*      */             }
/*      */             catch (ServiceException e) {}
/*      */           }
/*      */         }
/*      */       }
/*      */       label228:
/*  245 */       if ((pms.modified != null) && (!pms.modified.isEmpty())) {
/*  246 */         for (PendingModifications.Change chg : pms.modified.values()) {
/*  247 */           if ((chg.what instanceof MailItem)) {
/*  248 */             MailItem item = (MailItem)chg.what;
/*  249 */             if (skipChangeSerialization(getParentSession().getMailbox(), item)) {
/*  250 */               if (ZimbraLog.session.isDebugEnabled()) {
/*  251 */                 ZimbraLog.session.debug("skipping serialization of too-large remote conversation: " + new ItemId(item));
/*      */               }
/*      */             }
/*      */             else
/*      */             {
/*  256 */               boolean isVisible = visible.contains(Integer.valueOf((item instanceof Folder) ? item.getId() : item.getFolderId()));
/*      */               
/*  258 */               boolean moved = (chg.why & 0x100) != 0;
/*  259 */               if ((item instanceof Conversation)) {
/*  260 */                 filtered.recordModified(item, chg.why | 0x817, (MailItem)chg.preModifyObj);
/*      */               }
/*  262 */               else if (isVisible) {
/*  263 */                 filtered.recordModified(item, chg.why, (MailItem)chg.preModifyObj);
/*      */                 
/*      */ 
/*  266 */                 if (((item instanceof Message)) && ((moved) || ((chg.why & 0x7) != 0))) {
/*  267 */                   forceConversationModification((Message)item, chg, pms, filtered, moved ? 2071 : 7);
/*      */                 }
/*      */                 
/*      */               }
/*  271 */               else if (moved) {
/*  272 */                 filtered.recordDeleted((MailItem)chg.preModifyObj);
/*      */                 
/*      */ 
/*  275 */                 if ((item instanceof Message)) {
/*  276 */                   forceConversationModification((Message)item, chg, pms, filtered, 2071);
/*      */                 }
/*      */               }
/*      */             }
/*  280 */           } else if (((chg.what instanceof Mailbox)) && 
/*  281 */             (((Mailbox)chg.what).hasFullAccess(new OperationContext(getAuthenticatedAccountId())))) {
/*  282 */             filtered.recordModified((Mailbox)chg.what, chg.why);
/*      */           }
/*      */         }
/*      */       }
/*      */       
/*      */ 
/*  288 */       return filtered;
/*      */     }
/*      */     
/*      */     private void forceConversationModification(Message msg, PendingModifications.Change chg, PendingModifications pms, PendingModifications filtered, int changeMask)
/*      */     {
/*  293 */       int convId = msg.getConversationId();
/*  294 */       Mailbox mbox = msg.getMailbox();
/*  295 */       PendingModifications.ModificationKey mkey = new PendingModifications.ModificationKey(mbox.getAccountId(), Integer.valueOf(convId));
/*      */       
/*  297 */       if ((pms.created == null) || (!pms.created.containsKey(mkey))) {
/*      */         PendingModifications.Change existing;
/*  299 */         if ((pms.modified != null) && ((existing = (PendingModifications.Change)pms.modified.get(mkey)) != null)) {
/*  300 */           filtered.recordModified((MailItem)existing.what, existing.why | changeMask, (MailItem)existing.preModifyObj);
/*      */         } else
/*      */           try
/*      */           {
/*  304 */             filtered.recordModified(mbox.getConversationById(null, convId), changeMask);
/*      */           } catch (ServiceException e) {
/*  306 */             ZimbraLog.session.warn("exception during forceConversationModification", e);
/*      */           }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   private class RemoteSessionInfo {
/*      */     final String mServerId;
/*      */     final String mSessionId;
/*      */     final long mLastRequest;
/*      */     long mLastFailedPing;
/*      */     
/*  318 */     RemoteSessionInfo(String sessionId, String serverId, long lastPoll) { this.mSessionId = sessionId;this.mServerId = serverId;this.mLastRequest = lastPoll;
/*      */     }
/*      */   }
/*      */   
/*      */   public static class RemoteNotifications {
/*  323 */     int count = -1;
/*      */     String deleted;
/*      */     List<Element> created;
/*      */     List<Element> modified;
/*      */     List<Element> activities;
/*      */     
/*      */     public RemoteNotifications(Element eNotify) {
/*  330 */       if (eNotify == null)
/*      */         return;
/*      */       Element eSection;
/*  333 */       if ((eSection = eNotify.getOptionalElement("deleted")) != null)
/*  334 */         this.deleted = eSection.getAttribute("id", null);
/*  335 */       if ((eSection = eNotify.getOptionalElement("created")) != null)
/*  336 */         this.created = new ArrayList(eSection.listElements());
/*  337 */       if ((eSection = eNotify.getOptionalElement("modified")) != null)
/*  338 */         this.modified = new ArrayList(eSection.listElements());
/*  339 */       this.activities = eNotify.listElements("a");
/*  340 */       if (this.activities.isEmpty()) this.activities = null;
/*      */     }
/*      */     
/*      */     RemoteNotifications add(RemoteNotifications rns) {
/*  344 */       if (rns == null) {
/*  345 */         return this;
/*      */       }
/*      */       
/*  348 */       if (this.deleted == null) { this.deleted = rns.deleted;
/*  349 */       } else if (rns.deleted != null) { this.deleted = (this.deleted + "," + rns.deleted);
/*      */       }
/*  351 */       if (this.created == null) { this.created = rns.created;
/*  352 */       } else if (rns.created != null) { this.created.addAll(rns.created);
/*      */       }
/*  354 */       if (this.modified == null) { this.modified = rns.modified;
/*  355 */       } else if (rns.modified != null) { this.modified.addAll(rns.modified);
/*      */       }
/*  357 */       if (this.activities == null) { this.activities = rns.activities;
/*  358 */       } else if (rns.activities != null) { this.activities.addAll(rns.activities);
/*      */       }
/*  360 */       this.count = ((this.count >= 0) && (rns.count >= 0) ? this.count + rns.count : -1);
/*  361 */       return this;
/*      */     }
/*      */     
/*      */     int getScaledNotificationCount() {
/*  365 */       if (this.count == -1) {
/*  366 */         this.count = 0;
/*  367 */         if (this.deleted != null) this.count += StringUtil.countOccurrences(this.deleted, ',') / 4 + 1;
/*  368 */         if (this.created != null) this.count += this.created.size();
/*  369 */         if (this.modified != null) this.count += this.modified.size();
/*  370 */         if (this.activities != null) this.count += this.activities.size();
/*      */       }
/*  372 */       return this.count;
/*      */     }
/*      */     
/*      */     boolean hasNotifications() {
/*  376 */       if ((this.deleted != null) && (!this.deleted.equals(""))) return true;
/*  377 */       if ((this.created != null) && (!this.created.isEmpty())) return true;
/*  378 */       if ((this.modified != null) && (!this.modified.isEmpty())) return true;
/*  379 */       if ((this.activities != null) && (!this.activities.isEmpty())) return true;
/*  380 */       return false;
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */   class QueuedNotifications
/*      */   {
/*      */     List<Session.ExternalEventNotification> mExternalNotifications;
/*      */     
/*      */     PendingModifications mMailboxChanges;
/*      */     SoapSession.RemoteNotifications mRemoteChanges;
/*      */     boolean mHasLocalChanges;
/*      */     private final int mSequence;
/*      */     
/*  394 */     int getSequence() { return this.mSequence; }
/*      */     
/*  396 */     QueuedNotifications(int seqno) { this.mSequence = seqno; }
/*      */     
/*      */     boolean hasNotifications() {
/*  399 */       return hasNotifications(false);
/*      */     }
/*      */     
/*      */     boolean hasNotifications(boolean localMailboxOnly) {
/*  403 */       if (localMailboxOnly ? this.mHasLocalChanges : (this.mMailboxChanges != null) && (this.mMailboxChanges.hasNotifications()))
/*  404 */         return true;
/*  405 */       if ((!localMailboxOnly) && (this.mRemoteChanges != null) && (this.mRemoteChanges.hasNotifications()))
/*  406 */         return true;
/*  407 */       if ((this.mExternalNotifications != null) && (!this.mExternalNotifications.isEmpty()))
/*  408 */         return true;
/*  409 */       return false;
/*      */     }
/*      */     
/*      */     int getScaledNotificationCount() {
/*  413 */       return (this.mMailboxChanges == null ? 0 : this.mMailboxChanges.getScaledNotificationCount()) + (this.mRemoteChanges == null ? 0 : this.mRemoteChanges.getScaledNotificationCount());
/*      */     }
/*      */     
/*      */     void addNotification(Session.ExternalEventNotification extra)
/*      */     {
/*  418 */       if (this.mExternalNotifications == null)
/*  419 */         this.mExternalNotifications = new LinkedList();
/*  420 */       this.mExternalNotifications.add(extra);
/*      */     }
/*      */     
/*      */     void addNotification(PendingModifications pms) {
/*  424 */       if ((pms == null) || (!pms.hasNotifications()))
/*  425 */         return;
/*  426 */       if (this.mMailboxChanges == null)
/*  427 */         this.mMailboxChanges = new PendingModifications();
/*  428 */       this.mMailboxChanges.add(pms);
/*  429 */       if (!this.mHasLocalChanges)
/*  430 */         this.mHasLocalChanges |= pms.overlapsWithAccount(SoapSession.this.mAuthenticatedAccountId);
/*      */     }
/*      */     
/*      */     void addNotification(SoapSession.RemoteNotifications rns) {
/*  434 */       if (this.mRemoteChanges == null) {
/*  435 */         this.mRemoteChanges = rns;
/*      */       } else
/*  437 */         this.mRemoteChanges.add(rns);
/*      */     }
/*      */     
/*      */     void clearMailboxChanges() {
/*  441 */       this.mMailboxChanges = null;
/*  442 */       this.mRemoteChanges = null;
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*  447 */   static final long SOAP_SESSION_TIMEOUT_MSEC = Math.max(5, LC.zimbra_session_timeout_soap.intValue()) * 1000L;
/*      */   
/*      */   private static final long MINIMUM_PING_RETRY_TIME = 30000L;
/*  450 */   private static final int MAX_QUEUED_NOTIFICATIONS = LC.zimbra_session_max_pending_notifications.intValue();
/*      */   
/*      */ 
/*  453 */   private String queryString = "";
/*  454 */   private String groupBy = "";
/*  455 */   private String sortBy = "";
/*      */   private ZimbraQueryResults queryResults;
/*      */   private int recentMessages;
/*  458 */   private long previousAccess = -1L;
/*  459 */   private long lastWrite = -1L;
/*      */   
/*      */   protected int forceRefresh;
/*      */   
/*  463 */   protected LinkedList<QueuedNotifications> sentChanges = new LinkedList();
/*  464 */   protected QueuedNotifications changes = new QueuedNotifications(1);
/*      */   private PushChannel pushChannel;
/*      */   private boolean unregistered;
/*  467 */   private final Map<String, DelegateSession> delegateSessions = new HashMap(3);
/*      */   private List<RemoteSessionInfo> remoteSessions;
/*      */   private final boolean asAdmin;
/*  470 */   private boolean isOffline = false;
/*      */   private final SoapProtocol responseProtocol;
/*      */   private static final int DELEGATED_CONVERSATION_SIZE_LIMIT = 50;
/*      */   protected static final String A_ID = "id";
/*      */   private static ActivityCallback activityCb;
/*      */   
/*      */   public SoapSession(ZimbraSoapContext zsc) {
/*  477 */     super(zsc.getAuthtokenAccountId(), zsc.getAuthtokenAccountId(), Session.Type.SOAP);
/*  478 */     this.asAdmin = zsc.isUsingAdminPrivileges();
/*  479 */     this.responseProtocol = zsc.getResponseProtocol();
/*      */   }
/*      */   
/*      */   public SoapSession register() throws ServiceException
/*      */   {
/*  484 */     super.register();
/*      */     
/*  486 */     Mailbox mbox = this.mailbox;
/*  487 */     if (mbox != null) {
/*  488 */       this.recentMessages = mbox.getRecentMessageCount();
/*  489 */       this.previousAccess = mbox.getLastSoapAccessTime();
/*  490 */       this.unregistered = false;
/*  491 */       ZimbraLog.session.debug("initializing session recent count to %d", new Object[] { Integer.valueOf(this.recentMessages) });
/*      */     }
/*  493 */     return this;
/*      */   }
/*      */   
/*      */ 
/*      */   public SoapSession unregister()
/*      */   {
/*  499 */     Mailbox mbox = this.mailbox;
/*  500 */     if ((this.lastWrite != -1L) && (mbox != null)) {
/*      */       try {
/*  502 */         mbox.recordLastSoapAccessTime(this.lastWrite);
/*      */       } catch (OutOfMemoryError e) {
/*  504 */         Zimbra.halt("out of memory", e);
/*      */       } catch (Throwable t) {
/*  506 */         ZimbraLog.session.warn("exception recording unloaded session's last access time", t);
/*      */       }
/*      */     }
/*      */     
/*      */     List<DelegateSession> delegates;
/*      */     
/*  512 */     synchronized (this.delegateSessions) {
/*  513 */       delegates = new ArrayList(this.delegateSessions.values());
/*  514 */       this.delegateSessions.clear();
/*  515 */       this.unregistered = true;
/*      */     }
/*  517 */     for (DelegateSession ds : delegates) {
/*  518 */       ds.unregister();
/*      */     }
/*      */     
/*  521 */     super.unregister();
/*  522 */     return this;
/*      */   }
/*      */   
/*      */   protected boolean isMailboxListener()
/*      */   {
/*  527 */     return true;
/*      */   }
/*      */   
/*      */   protected boolean isRegisteredInCache()
/*      */   {
/*  532 */     return true;
/*      */   }
/*      */   
/*      */   protected long getSessionIdleLifetime()
/*      */   {
/*  537 */     return SOAP_SESSION_TIMEOUT_MSEC;
/*      */   }
/*      */   
/*      */   public boolean isOfflineSoapSession() {
/*  541 */     return this.isOffline;
/*      */   }
/*      */   
/*      */   public void setOfflineSoapSession() {
/*  545 */     this.isOffline = true;
/*      */   }
/*      */   
/*      */   private boolean asAdmin() {
/*  549 */     return this.asAdmin;
/*      */   }
/*      */   
/*      */   public Session getDelegateSession(String targetAccountId) {
/*  553 */     if ((this.unregistered) || (targetAccountId == null)) {
/*  554 */       return null;
/*      */     }
/*      */     try
/*      */     {
/*  558 */       if (!Provisioning.onLocalServer(Provisioning.getInstance().get(Key.AccountBy.id, targetAccountId))) {
/*  559 */         return null;
/*      */       }
/*      */     } catch (ServiceException e) {
/*  562 */       ZimbraLog.session.info("exception while fetching delegate session", e);
/*  563 */       return null;
/*      */     }
/*      */     
/*      */ 
/*  567 */     targetAccountId = targetAccountId.toLowerCase();
/*  568 */     if (targetAccountId.equalsIgnoreCase(this.mAuthenticatedAccountId)) {
/*  569 */       return this;
/*      */     }
/*  571 */     synchronized (this.delegateSessions)
/*      */     {
/*  573 */       if (this.unregistered) {
/*  574 */         return null;
/*      */       }
/*  576 */       DelegateSession ds = (DelegateSession)this.delegateSessions.get(targetAccountId);
/*  577 */       if (ds == null) {
/*  578 */         ds = new DelegateSession(this.mAuthenticatedAccountId, targetAccountId).register();
/*  579 */         if (ds != null) {
/*  580 */           this.delegateSessions.put(targetAccountId, ds);
/*      */         }
/*      */       }
/*  583 */       return ds;
/*      */     }
/*      */   }
/*      */   
/*      */   void removeDelegateSession(DelegateSession ds) {
/*  588 */     synchronized (this.delegateSessions) {
/*  589 */       if ((this.unregistered) || (this.delegateSessions.isEmpty())) {
/*  590 */         return;
/*      */       }
/*  592 */       boolean removed = this.delegateSessions.remove(ds.mTargetAccountId.toLowerCase()) != null;
/*  593 */       if (!removed) {
/*  594 */         return;
/*      */       }
/*      */     }
/*  597 */     synchronized (this.sentChanges) {
/*  598 */       int force = this.changes.getSequence();
/*  599 */       ZimbraLog.session.debug("removeDelegateSession: changing mForceRefresh: %d -> %d", new Object[] { Integer.valueOf(this.forceRefresh), Integer.valueOf(force) });
/*  600 */       this.forceRefresh = force;
/*      */     }
/*      */   }
/*      */   
/*      */   public synchronized String getRemoteSessionId(Server server)
/*      */   {
/*  606 */     if ((this.mailbox == null) || (this.remoteSessions == null) || (server == null)) {
/*  607 */       return null;
/*      */     }
/*  609 */     for (RemoteSessionInfo rsi : this.remoteSessions) {
/*  610 */       if (rsi.mServerId.equals(server.getId())) {
/*  611 */         return rsi.mSessionId;
/*      */       }
/*      */     }
/*  614 */     return null;
/*      */   }
/*      */   
/*      */   protected boolean registerRemoteSessionId(Server server, String sessionId) {
/*  618 */     if ((this.mailbox == null) || (server == null) || (sessionId == null)) {
/*  619 */       return true;
/*      */     }
/*  621 */     String serverId = server.getId().toLowerCase();
/*  622 */     synchronized (this) {
/*  623 */       boolean isNewEntry = true;
/*  624 */       Iterator<RemoteSessionInfo> it; if (this.remoteSessions == null) {
/*  625 */         this.remoteSessions = new LinkedList();
/*      */       } else {
/*  627 */         for (it = this.remoteSessions.iterator(); it.hasNext();) {
/*  628 */           if (((RemoteSessionInfo)it.next()).mServerId.equals(server.getId())) {
/*  629 */             it.remove();
/*  630 */             isNewEntry = false;
/*      */           }
/*      */         }
/*      */       }
/*  634 */       this.remoteSessions.add(new RemoteSessionInfo(sessionId, serverId, System.currentTimeMillis()));
/*  635 */       return isNewEntry;
/*      */     }
/*      */   }
/*      */   
/*      */   public void handleRemoteNotifications(Server server, Element context) {
/*  640 */     handleRemoteNotifications(server, context, false, false);
/*      */   }
/*      */   
/*      */   protected void handleRemoteNotifications(Server server, Element context, boolean ignoreRefresh, boolean isPing) {
/*  644 */     if (context == null) {
/*  645 */       return;
/*      */     }
/*  647 */     boolean refreshExpected = true;
/*      */     
/*      */ 
/*  650 */     Element eSession = context.getOptionalElement("session");
/*  651 */     boolean isSoap = (eSession != null) && (eSession.getAttribute("type", null) == null);
/*  652 */     String sessionId = eSession == null ? null : eSession.getAttribute("id", null);
/*  653 */     if ((isSoap) && (sessionId != null) && (!sessionId.equals(""))) {
/*  654 */       refreshExpected = registerRemoteSessionId(server, sessionId);
/*      */     }
/*      */     
/*  657 */     if ((!ignoreRefresh) && (!refreshExpected) && (context.getOptionalElement("refresh") != null)) {
/*  658 */       int force = getCurrentNotificationSequence();
/*  659 */       ZimbraLog.session.debug("handleRemoteNotifications: changing mForceRefresh: %d -> %d", new Object[] { Integer.valueOf(this.forceRefresh), Integer.valueOf(force) });
/*  660 */       this.forceRefresh = force;
/*      */     }
/*      */     
/*  663 */     Element eNotify = context.getOptionalElement("notify");
/*  664 */     if (eNotify != null) {
/*  665 */       RemoteNotifications rns = new RemoteNotifications(eNotify);
/*  666 */       synchronized (this.sentChanges) {
/*  667 */         if (!skipNotifications(rns.getScaledNotificationCount(), !isPing)) {
/*  668 */           addRemoteNotifications(rns);
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   public void addRemoteNotifications(RemoteNotifications rns) {
/*  675 */     this.changes.addNotification(rns);
/*      */   }
/*      */   
/*      */   private void pingRemoteSessions(ZimbraSoapContext zsc) {
/*  679 */     long now = System.currentTimeMillis();
/*      */     
/*  681 */     List<RemoteSessionInfo> needsPing = null;
/*  682 */     long cutoff; synchronized (this) {
/*  683 */       if (this.remoteSessions == null) {
/*  684 */         return;
/*      */       }
/*  686 */       cutoff = now - getSessionIdleLifetime() / 2L;
/*  687 */       for (RemoteSessionInfo rsi : this.remoteSessions) {
/*  688 */         if ((rsi.mLastRequest < cutoff) && (now - rsi.mLastFailedPing > 30000L)) {
/*  689 */           if (needsPing == null) {
/*  690 */             needsPing = new LinkedList();
/*      */           }
/*  692 */           needsPing.add(rsi);
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*  697 */     if (needsPing == null) {
/*  698 */       return;
/*      */     }
/*  700 */     Provisioning prov = Provisioning.getInstance();
/*  701 */     for (RemoteSessionInfo rsi : needsPing) {
/*      */       try {
/*  703 */         Element noop = Element.create(zsc.getRequestProtocol(), MailConstants.NO_OP_REQUEST);
/*  704 */         Server server = prov.getServerById(rsi.mServerId);
/*      */         
/*  706 */         ZimbraSoapContext zscProxy = new ZimbraSoapContext(zsc, this.mAuthenticatedAccountId);
/*  707 */         zscProxy.setProxySession(rsi.mSessionId);
/*      */         
/*  709 */         ProxyTarget proxy = new ProxyTarget(server, zscProxy.getAuthToken(), URLUtil.getSoapURL(server, false));
/*  710 */         proxy.disableRetries().setTimeouts(10000L);
/*  711 */         Pair<Element, Element> envelope = proxy.execute(noop.detach(), zscProxy);
/*  712 */         handleRemoteNotifications(server, (Element)envelope.getFirst(), true, true);
/*      */       } catch (ServiceException e) {
/*  714 */         rsi.mLastFailedPing = now;
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public int getRecentMessageCount()
/*      */   {
/*  725 */     return this.recentMessages;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public long getPreviousSessionTime()
/*      */   {
/*  732 */     return this.previousAccess;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public long getLastWriteAccessTime()
/*      */   {
/*  739 */     return this.lastWrite == -1L ? this.previousAccess : this.lastWrite;
/*      */   }
/*      */   
/*      */ 
/*      */   public void doEncodeState(Element parent)
/*      */   {
/*  745 */     if (this.pushChannel != null)
/*  746 */       parent.addAttribute("push", true);
/*      */   }
/*      */   
/*      */   public static abstract interface PushChannel {
/*      */     public abstract void closePushChannel();
/*      */     
/*      */     public abstract int getLastKnownSequence();
/*      */     
/*      */     public abstract ZimbraSoapContext getSoapContext();
/*      */     
/*      */     public abstract boolean localChangesOnly();
/*      */     
/*      */     public abstract boolean isPersistent();
/*      */     
/*      */     public abstract void notificationsReady() throws ServiceException;
/*      */   }
/*      */   
/*  763 */   public static enum RegisterNotificationResult { NO_NOTIFY, 
/*  764 */     DATA_READY, 
/*  765 */     BLOCKING;
/*      */     
/*      */ 
/*      */ 
/*      */     private RegisterNotificationResult() {}
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public synchronized RegisterNotificationResult registerNotificationConnection(PushChannel sc)
/*      */     throws ServiceException
/*      */   {
/*  777 */     if (this.pushChannel != null) {
/*  778 */       this.pushChannel.closePushChannel();
/*  779 */       this.pushChannel = null;
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  788 */     if ((isMailboxListener()) && (this.mailbox == null)) {
/*  789 */       sc.closePushChannel();
/*  790 */       return RegisterNotificationResult.NO_NOTIFY;
/*      */     }
/*      */     
/*      */     boolean dataReady;
/*  794 */     synchronized (this.sentChanges)
/*      */     {
/*  796 */       int lastSeqNo = sc.getLastKnownSequence();
/*  797 */       dataReady = this.changes.hasNotifications(sc.localChangesOnly());
/*  798 */       if ((!dataReady) && (this.changes.getSequence() > lastSeqNo + 1) && (!this.sentChanges.isEmpty())) {
/*  799 */         for (Iterator i$ = this.sentChanges.iterator(); i$.hasNext(); 
/*      */             
/*  801 */             goto 165)
/*      */         {
/*  799 */           QueuedNotifications ntfn = (QueuedNotifications)i$.next();
/*  800 */           if ((ntfn.getSequence() > lastSeqNo) && (ntfn.hasNotifications(sc.localChangesOnly()))) {
/*  801 */             dataReady = true;
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*  806 */     if (dataReady) {
/*  807 */       sc.notificationsReady();
/*  808 */       return RegisterNotificationResult.DATA_READY;
/*      */     }
/*  810 */     this.pushChannel = sc;
/*  811 */     return RegisterNotificationResult.BLOCKING;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public void notifyExternalEvent(Session.ExternalEventNotification extra)
/*      */   {
/*  818 */     if (extra == null) {
/*  819 */       return;
/*      */     }
/*  821 */     synchronized (this.sentChanges) {
/*  822 */       this.changes.addNotification(extra);
/*      */     }
/*      */     try
/*      */     {
/*  826 */       notifyPushChannel(null);
/*      */     } catch (ServiceException e) {
/*  828 */       ZimbraLog.session.warn("ServiceException in notifyExternalEvent", e);
/*      */     }
/*      */   }
/*      */   
/*      */   public void updateLastWrite(Mailbox mbox)
/*      */   {
/*  834 */     boolean firstWrite = this.lastWrite == -1L;
/*  835 */     this.lastWrite = System.currentTimeMillis();
/*  836 */     if (firstWrite) {
/*      */       try {
/*  838 */         mbox.recordLastSoapAccessTime(this.lastWrite);
/*      */       } catch (ServiceException e) {
/*  840 */         ZimbraLog.session.warn("ServiceException in notifyPendingChanges ", e);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public void notifyPendingChanges(PendingModifications pms, int changeId, Session source)
/*      */   {
/*  858 */     Mailbox mbox = this.mailbox;
/*  859 */     if ((pms == null) || (mbox == null) || (!pms.hasNotifications())) {
/*  860 */       return;
/*      */     }
/*  862 */     if (source == this) {
/*  863 */       updateLastWrite(mbox);
/*      */ 
/*      */     }
/*  866 */     else if (pms.created != null) {
/*  867 */       for (MailItem item : pms.created.values()) {
/*  868 */         if ((item instanceof Message)) {
/*  869 */           boolean isReceived = true;
/*  870 */           if ((item.getFolderId() == 4) || (item.getFolderId() == 3)) {
/*  871 */             isReceived = false;
/*  872 */           } else if ((item.getFlagBitmask() & Mailbox.NON_DELIVERY_FLAGS) != 0) {
/*  873 */             isReceived = false;
/*  874 */           } else if (source != null) {
/*  875 */             isReceived = false;
/*      */           }
/*  877 */           if (isReceived) {
/*  878 */             this.recentMessages += 1;
/*  879 */             ZimbraLog.session.debug("incrementing session recent count to %d", new Object[] { Integer.valueOf(this.recentMessages) });
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*      */ 
/*  886 */     handleNotifications(pms, source == this);
/*      */   }
/*      */   
/*      */   boolean hasSerializableChanges(PendingModifications pms)
/*      */   {
/*  891 */     if ((pms.created != null) && (!pms.created.isEmpty())) {
/*  892 */       return true;
/*      */     }
/*  894 */     if ((pms.deleted != null) && (!pms.deleted.isEmpty())) {
/*  895 */       return true;
/*      */     }
/*  897 */     if ((pms.modified != null) && (!pms.modified.isEmpty())) {
/*  898 */       for (PendingModifications.Change chg : pms.modified.values()) {
/*  899 */         if ((!(chg.what instanceof Mailbox)) || (chg.why != 8)) {
/*  900 */           return true;
/*      */         }
/*      */       }
/*      */     }
/*  904 */     return false;
/*      */   }
/*      */   
/*      */   void handleNotifications(PendingModifications pms, boolean fromThisSession) {
/*  908 */     if (!hasSerializableChanges(pms)) {
/*  909 */       return;
/*      */     }
/*      */     try
/*      */     {
/*  913 */       cacheNotifications(pms, fromThisSession);
/*      */       
/*  915 */       notifyPushChannel(pms);
/*      */       
/*  917 */       clearCachedQueryResults();
/*      */     } catch (ServiceException e) {
/*  919 */       ZimbraLog.session.warn("ServiceException in notifyPendingChanges ", e);
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */   private void cacheNotifications(PendingModifications pms, boolean fromThisSession)
/*      */   {
/*  926 */     synchronized (this.sentChanges) {
/*  927 */       if (!skipNotifications(pms.getScaledNotificationCount(), fromThisSession))
/*      */       {
/*      */ 
/*      */ 
/*  931 */         this.changes.addNotification(pms);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   protected boolean skipNotifications(int notificationCount, boolean fromThisSession)
/*      */   {
/*  938 */     int currentSequence = getCurrentNotificationSequence();
/*  939 */     if ((this.forceRefresh == currentSequence) && (!fromThisSession)) {
/*  940 */       return true;
/*      */     }
/*      */     int count;
/*  943 */     if ((this.forceRefresh != currentSequence) && (MAX_QUEUED_NOTIFICATIONS > 0))
/*      */     {
/*  945 */       count = notificationCount + this.changes.getScaledNotificationCount();
/*  946 */       if (count > MAX_QUEUED_NOTIFICATIONS)
/*      */       {
/*  948 */         this.changes.clearMailboxChanges();
/*  949 */         int force = currentSequence;
/*  950 */         ZimbraLog.session.debug("skipNotifications: changing mForceRefresh: %d -> %d", new Object[] { Integer.valueOf(this.forceRefresh), Integer.valueOf(force) });
/*  951 */         this.forceRefresh = force;
/*      */       }
/*      */       
/*  954 */       for (QueuedNotifications ntfn : this.sentChanges) {
/*  955 */         count += ntfn.getScaledNotificationCount();
/*  956 */         if (count > MAX_QUEUED_NOTIFICATIONS) {
/*  957 */           ntfn.clearMailboxChanges();
/*  958 */           int force = Math.max(this.forceRefresh, ntfn.getSequence());
/*  959 */           ZimbraLog.session.debug("skipNotifications: changing mForceRefresh: %d -> %d", new Object[] { Integer.valueOf(this.forceRefresh), Integer.valueOf(force) });
/*  960 */           this.forceRefresh = force;
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*  965 */     return (this.forceRefresh == currentSequence) && (!fromThisSession);
/*      */   }
/*      */   
/*      */   public void forcePush() {
/*      */     try {
/*  970 */       notifyPushChannel(null, false);
/*      */     } catch (ServiceException e) {
/*  972 */       ZimbraLog.session.warn("ServiceException in forcePush", e);
/*      */     }
/*      */   }
/*      */   
/*      */   private synchronized void notifyPushChannel(PendingModifications pms) throws ServiceException
/*      */   {
/*  978 */     boolean persistent = this.pushChannel == null ? false : this.pushChannel.isPersistent();
/*  979 */     notifyPushChannel(pms, !persistent);
/*      */   }
/*      */   
/*      */   private synchronized void notifyPushChannel(PendingModifications pms, boolean clearChannel)
/*      */     throws ServiceException
/*      */   {
/*  985 */     if (this.pushChannel == null) {
/*  986 */       return;
/*      */     }
/*      */     
/*  989 */     if ((this.pushChannel.localChangesOnly()) && (pms != null) && (!pms.overlapsWithAccount(this.mAuthenticatedAccountId))) {
/*  990 */       return;
/*      */     }
/*  992 */     this.pushChannel.notificationsReady();
/*  993 */     if (clearChannel) {
/*  994 */       this.pushChannel = null;
/*      */     }
/*      */   }
/*      */   
/*      */   public boolean requiresRefresh(int lastSequence)
/*      */   {
/* 1000 */     synchronized (this.sentChanges) {
/* 1001 */       boolean required = false;
/* 1002 */       int currentSeq = getCurrentNotificationSequence();
/* 1003 */       if (lastSequence <= 0) {
/* 1004 */         required = this.forceRefresh == currentSeq;
/*      */       } else {
/* 1006 */         required = this.forceRefresh > Math.min(lastSequence, currentSeq);
/*      */       }
/* 1008 */       ZimbraLog.session.debug("refresh required: forceRefresh=%d,lastSequence=%d,currentSequence=%d", new Object[] { Integer.valueOf(this.forceRefresh), Integer.valueOf(lastSequence), Integer.valueOf(currentSeq) });
/*      */       
/* 1010 */       return required;
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public void putRefresh(Element ctxt, ZimbraSoapContext zsc)
/*      */     throws ServiceException
/*      */   {
/* 1026 */     Mailbox mbox = this.mailbox;
/* 1027 */     if (mbox == null) {
/* 1028 */       return;
/*      */     }
/* 1030 */     synchronized (this.sentChanges) {
/* 1031 */       for (QueuedNotifications ntfn : this.sentChanges) {
/* 1032 */         ntfn.clearMailboxChanges();
/*      */       }
/*      */     }
/*      */     
/* 1036 */     Element eRefresh = ctxt.addUniqueElement("refresh");
/* 1037 */     eRefresh.addAttribute("version", BuildInfo.FULL_VERSION, Element.Disposition.CONTENT);
/*      */     
/* 1039 */     OperationContext octxt = DocumentHandler.getOperationContext(zsc, this);
/* 1040 */     ItemIdFormatter ifmt = new ItemIdFormatter(zsc);
/*      */     
/*      */ 
/* 1043 */     ToXML.encodeMailbox(eRefresh, octxt, mbox);
/*      */     
/*      */ 
/* 1046 */     Object tags = mbox.getTagList(octxt);
/* 1047 */     Element eTags; if ((tags != null) && (((List)tags).size() > 0)) {
/* 1048 */       eTags = eRefresh.addUniqueElement("tags");
/* 1049 */       for (Tag tag : (List)tags) {
/* 1050 */         if ((tag != null) && (!(tag instanceof Flag))) {
/* 1051 */           ToXML.encodeTag(eTags, ifmt, octxt, tag);
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*      */ 
/* 1057 */     Mailbox.FolderNode root = mbox.getFolderTree(octxt, null, false);
/* 1058 */     OperationContextData.setNeedGranteeName(octxt, false);
/* 1059 */     GetFolder.encodeFolderNode(root, eRefresh, ifmt, octxt);
/*      */     
/*      */ 
/* 1062 */     Map<ItemId, Pair<Boolean, Element>> mountpoints = new HashMap();
/*      */     
/* 1064 */     expandLocalMountpoints(octxt, root, eRefresh.getFactory(), mountpoints);
/*      */     
/* 1066 */     expandRemoteMountpoints(octxt, zsc, mountpoints);
/*      */     
/*      */ 
/* 1069 */     if (!mountpoints.isEmpty()) {
/* 1070 */       transferMountpointContents(eRefresh.getOptionalElement("folder"), octxt, mountpoints);
/*      */     }
/*      */   }
/*      */   
/*      */   private void expandLocalMountpoints(OperationContext octxt, Mailbox.FolderNode node, Element.ElementFactory factory, Map<ItemId, Pair<Boolean, Element>> mountpoints)
/*      */   {
/* 1076 */     if ((node.mFolder == null) || (mountpoints == null))
/* 1077 */       return;
/* 1078 */     if ((node.mFolder instanceof Mountpoint)) {
/* 1079 */       Mountpoint mpt = (Mountpoint)node.mFolder;
/* 1080 */       expandLocalMountpoint(octxt, mpt, factory, mountpoints);
/*      */     } else {
/* 1082 */       for (Mailbox.FolderNode child : node.mSubfolders) {
/* 1083 */         expandLocalMountpoints(octxt, child, factory, mountpoints);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */   private void expandLocalMountpoint(OperationContext octxt, Mountpoint mpt, Element.ElementFactory factory, Map<ItemId, Pair<Boolean, Element>> mountpoints)
/*      */   {
/* 1091 */     ItemId iidTarget = mpt.getTarget();
/* 1092 */     if (mountpoints.containsKey(iidTarget)) {
/* 1093 */       return;
/*      */     }
/*      */     try {
/* 1096 */       Provisioning prov = Provisioning.getInstance();
/* 1097 */       Account owner = prov.get(Key.AccountBy.id, mpt.getOwnerId(), octxt.getAuthToken());
/* 1098 */       if ((owner == null) || (owner.getId().equals(this.mAuthenticatedAccountId))) {
/* 1099 */         mountpoints.put(iidTarget, new Pair(Boolean.valueOf(true), null));
/* 1100 */         return;
/*      */       }
/*      */       
/*      */ 
/*      */ 
/* 1105 */       if (("maintenance".equals(owner.getAccountStatus(prov))) || ((!"active".equals(owner.getAccountStatus(prov))) && ((!octxt.isUsingAdminPrivileges()) || (!AccessManager.getInstance().canAccessAccount(octxt.getAuthenticatedUser(), owner)))))
/*      */       {
/*      */ 
/*      */ 
/* 1109 */         mountpoints.put(iidTarget, new Pair(Boolean.valueOf(true), null));
/* 1110 */         return;
/*      */       }
/*      */       
/*      */ 
/* 1114 */       if (!Provisioning.onLocalServer(owner)) {
/* 1115 */         mountpoints.put(iidTarget, null);
/* 1116 */         return;
/*      */       }
/*      */       
/* 1119 */       Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(owner);
/* 1120 */       Mailbox.FolderNode remote = mbox.getFolderTree(octxt, new ItemId(mbox, mpt.getRemoteId()), false);
/*      */       
/* 1122 */       if ((remote != null) && (remote.mFolder != null) && (!remote.mFolder.isHidden())) {
/* 1123 */         ItemIdFormatter ifmt = new ItemIdFormatter(octxt.getAuthenticatedUser(), mbox, false);
/* 1124 */         if (OperationContextData.getNeedGranteeName(octxt)) {
/* 1125 */           OperationContextData.addGranteeNames(octxt, remote);
/*      */         }
/* 1127 */         Element subhierarchy = GetFolder.encodeFolderNode(remote, factory.createElement("ignored"), ifmt, octxt).detach();
/* 1128 */         mountpoints.put(iidTarget, new Pair(Boolean.valueOf(false), subhierarchy));
/*      */         
/* 1130 */         getDelegateSession(mpt.getOwnerId());
/*      */       }
/*      */     } catch (ServiceException e) {
/* 1133 */       mountpoints.put(iidTarget, new Pair(Boolean.valueOf(true), null));
/*      */     }
/*      */   }
/*      */   
/*      */   private void expandRemoteMountpoints(OperationContext octxt, ZimbraSoapContext zsc, Map<ItemId, Pair<Boolean, Element>> mountpoints)
/*      */   {
/* 1139 */     Map<String, Server> remoteServers = null;
/* 1140 */     Provisioning prov = Provisioning.getInstance();
/* 1141 */     for (Map.Entry<ItemId, Pair<Boolean, Element>> mptinfo : mountpoints.entrySet())
/*      */       try
/*      */       {
/* 1144 */         if (mptinfo.getValue() == null)
/*      */         {
/*      */ 
/* 1147 */           Account owner = prov.get(Key.AccountBy.id, ((ItemId)mptinfo.getKey()).getAccountId(), zsc.getAuthToken());
/* 1148 */           if (owner != null)
/*      */           {
/*      */ 
/* 1151 */             Server server = prov.getServer(owner);
/* 1152 */             if (server != null)
/*      */             {
/*      */ 
/* 1155 */               if (remoteServers == null) {
/* 1156 */                 remoteServers = new HashMap(3);
/*      */               }
/* 1158 */               remoteServers.put(owner.getId(), server);
/*      */             }
/*      */           }
/*      */         } } catch (ServiceException e) {}
/*      */     Map<String, Element> remoteHierarchies;
/* 1163 */     if ((remoteServers != null) && (!remoteServers.isEmpty())) {
/* 1164 */       remoteHierarchies = fetchRemoteHierarchies(octxt, zsc, remoteServers);
/* 1165 */       for (Map.Entry<ItemId, Pair<Boolean, Element>> mptinfo : mountpoints.entrySet())
/*      */       {
/* 1167 */         if (mptinfo.getValue() == null)
/*      */         {
/*      */ 
/* 1170 */           ItemId iid = (ItemId)mptinfo.getKey();
/* 1171 */           Element remoteFolderElement = findRemoteFolder(iid.toString(this.mAuthenticatedAccountId), (Element)remoteHierarchies.get(iid.getAccountId()));
/*      */           
/* 1173 */           mptinfo.setValue(new Pair(Boolean.valueOf(remoteFolderElement == null), remoteFolderElement));
/*      */         } }
/*      */     }
/*      */   }
/*      */   
/*      */   private Map<String, Element> fetchRemoteHierarchies(OperationContext octxt, ZimbraSoapContext zsc, Map<String, Server> remoteServers) {
/* 1179 */     Map<String, Element> hierarchies = new HashMap();
/*      */     Element noop;
/*      */     try
/*      */     {
/* 1183 */       noop = Element.create(zsc.getRequestProtocol(), MailConstants.GET_FOLDER_REQUEST).addAttribute("visible", true);
/* 1184 */       if (!OperationContextData.getNeedGranteeName(octxt)) {
/* 1185 */         noop.addAttribute("needGranteeName", false);
/*      */       }
/*      */     }
/*      */     catch (ServiceException e) {
/* 1189 */       return hierarchies;
/*      */     }
/*      */     
/* 1192 */     for (Map.Entry<String, Server> remote : remoteServers.entrySet()) {
/* 1193 */       String accountId = (String)remote.getKey();
/* 1194 */       Server server = (Server)remote.getValue();
/*      */       try
/*      */       {
/* 1197 */         ZimbraSoapContext zscProxy = new ZimbraSoapContext(zsc, accountId);
/* 1198 */         zscProxy.setProxySession(getRemoteSessionId(server));
/*      */         
/* 1200 */         ProxyTarget proxy = new ProxyTarget(server, zscProxy.getAuthToken(), URLUtil.getSoapURL(server, false));
/* 1201 */         proxy.disableRetries().setTimeouts(10000L);
/* 1202 */         Pair<Element, Element> envelope = proxy.execute(noop.detach(), zscProxy);
/* 1203 */         handleRemoteNotifications(server, (Element)envelope.getFirst(), true, true);
/* 1204 */         hierarchies.put(accountId, ((Element)envelope.getSecond()).getOptionalElement("folder"));
/*      */       }
/*      */       catch (ServiceException e) {}
/*      */     }
/* 1208 */     return hierarchies;
/*      */   }
/*      */   
/*      */   private static Element findRemoteFolder(String id, Element eFolder) {
/* 1212 */     if ((id == null) || (eFolder == null)) {
/* 1213 */       return null;
/*      */     }
/* 1215 */     if (id.equalsIgnoreCase(eFolder.getAttribute("id", null)))
/*      */     {
/* 1217 */       boolean isStub = eFolder.getAttribute("s", null) == null;
/* 1218 */       return isStub ? null : eFolder.clone();
/*      */     }
/*      */     
/* 1221 */     for (Element eSubfolder : eFolder.listElements()) {
/* 1222 */       Element match = findRemoteFolder(id, eSubfolder);
/* 1223 */       if (match != null)
/*      */       {
/* 1225 */         String folderPath = match.getAttribute("absFolderPath", null);
/* 1226 */         if (folderPath == null) {
/* 1227 */           folderPath = match.getAttribute("name", null);
/*      */         }
/* 1229 */         if ((folderPath != null) && (!folderPath.startsWith("/"))) {
/* 1230 */           String parentFolderName = eFolder.getAttribute("name", null);
/* 1231 */           if (parentFolderName != null) { String newPath;
/*      */             String newPath;
/* 1233 */             if (parentFolderName.equals("USER_ROOT")) {
/* 1234 */               newPath = "/" + folderPath;
/*      */             } else {
/* 1236 */               newPath = parentFolderName + "/" + folderPath;
/*      */             }
/* 1238 */             match.addAttribute("absFolderPath", newPath);
/*      */           }
/*      */         }
/* 1241 */         return match;
/*      */       }
/*      */     }
/* 1244 */     return null;
/*      */   }
/*      */   
/*      */   private static void transferMountpointContents(Element elem, OperationContext octxt, Map<ItemId, Pair<Boolean, Element>> mountpoints)
/*      */     throws ServiceException
/*      */   {
/* 1250 */     if (elem == null) {
/* 1251 */       return;
/*      */     }
/* 1253 */     Pair<Boolean, Element> target = null;
/* 1254 */     if (elem.getName().equals("link")) {
/* 1255 */       ItemId iidTarget = new ItemId(elem.getAttribute("zid", null), (int)elem.getAttributeLong("rid", -1L));
/* 1256 */       target = (Pair)mountpoints.get(iidTarget);
/*      */     }
/*      */     
/* 1259 */     if (target == null)
/*      */     {
/* 1261 */       for (Element child : elem.listElements()) {
/* 1262 */         transferMountpointContents(child, octxt, mountpoints);
/*      */       }
/*      */     } else {
/* 1265 */       boolean broken = ((Boolean)target.getFirst()).booleanValue();
/* 1266 */       if (broken) {
/* 1267 */         elem.addAttribute("broken", true);
/*      */       } else {
/* 1269 */         ToXML.transferMountpointContents(elem, (Element)target.getSecond());
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   /* Error */
/*      */   public int getCurrentNotificationSequence()
/*      */   {
/*      */     // Byte code:
/*      */     //   0: aload_0
/*      */     //   1: getfield 15	com/zimbra/cs/session/SoapSession:sentChanges	Ljava/util/LinkedList;
/*      */     //   4: dup
/*      */     //   5: astore_1
/*      */     //   6: monitorenter
/*      */     //   7: aload_0
/*      */     //   8: getfield 18	com/zimbra/cs/session/SoapSession:changes	Lcom/zimbra/cs/session/SoapSession$QueuedNotifications;
/*      */     //   11: invokevirtual 73	com/zimbra/cs/session/SoapSession$QueuedNotifications:getSequence	()I
/*      */     //   14: aload_1
/*      */     //   15: monitorexit
/*      */     //   16: ireturn
/*      */     //   17: astore_2
/*      */     //   18: aload_1
/*      */     //   19: monitorexit
/*      */     //   20: aload_2
/*      */     //   21: athrow
/*      */     // Line number table:
/*      */     //   Java source line #1276	-> byte code offset #0
/*      */     //   Java source line #1277	-> byte code offset #7
/*      */     //   Java source line #1278	-> byte code offset #17
/*      */     // Local variable table:
/*      */     //   start	length	slot	name	signature
/*      */     //   0	22	0	this	SoapSession
/*      */     //   5	14	1	Ljava/lang/Object;	Object
/*      */     //   17	4	2	localObject1	Object
/*      */     // Exception table:
/*      */     //   from	to	target	type
/*      */     //   7	16	17	finally
/*      */     //   17	20	17	finally
/*      */   }
/*      */   
/*      */   public void acknowledgeNotifications(int sequence)
/*      */   {
/*      */     Iterator<QueuedNotifications> it;
/* 1282 */     synchronized (this.sentChanges) {
/* 1283 */       if ((this.sentChanges == null) || (this.sentChanges.isEmpty())) {
/* 1284 */         return;
/*      */       }
/* 1286 */       if (sequence <= 0)
/*      */       {
/* 1288 */         this.sentChanges.clear();
/*      */       }
/*      */       else {
/* 1291 */         for (it = this.sentChanges.iterator(); (it.hasNext()) && 
/* 1292 */               (((QueuedNotifications)it.next()).getSequence() <= sequence);) {
/* 1293 */           it.remove();
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public Collection<PendingModifications> getNotifications()
/*      */   {
/* 1303 */     List<PendingModifications> ret = new ArrayList();
/* 1304 */     synchronized (this.sentChanges) {
/* 1305 */       for (QueuedNotifications notification : this.sentChanges) {
/* 1306 */         if (notification.hasNotifications()) {
/* 1307 */           ret.add(notification.mMailboxChanges);
/*      */         }
/*      */       }
/*      */     }
/* 1311 */     return ret;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public Element putNotifications(Element ctxt, ZimbraSoapContext zsc, int lastSequence)
/*      */   {
/* 1351 */     Mailbox mbox = this.mailbox;
/* 1352 */     if ((ctxt == null) || (mbox == null)) {
/* 1353 */       return null;
/*      */     }
/* 1355 */     if (Provisioning.getInstance().allowsPingRemote())
/*      */     {
/* 1357 */       pingRemoteSessions(zsc);
/*      */     }
/*      */     
/*      */     LinkedList<QueuedNotifications> notifications;
/*      */     
/* 1362 */     synchronized (this.sentChanges)
/*      */     {
/* 1364 */       ctxt.addUniqueElement("change").addAttribute("token", mbox.getLastChangeID());
/*      */       
/*      */ 
/* 1367 */       acknowledgeNotifications(lastSequence);
/*      */       
/*      */ 
/* 1370 */       if (this.sentChanges.size() > 20) {
/* 1371 */         ZimbraLog.session.warn("clearing abnormally long notification change list due to misbehaving client");
/* 1372 */         this.sentChanges.clear();
/*      */       }
/*      */       
/* 1375 */       if ((this.changes.hasNotifications()) || (requiresRefresh(lastSequence))) {
/* 1376 */         assert (this.changes.getSequence() >= 1);
/* 1377 */         int newSequence = this.changes.getSequence() + 1;
/* 1378 */         this.sentChanges.add(this.changes);
/* 1379 */         this.changes = new QueuedNotifications(newSequence);
/*      */       }
/*      */       
/*      */ 
/* 1383 */       assert (!this.changes.hasNotifications());
/*      */       
/*      */ 
/* 1386 */       if (this.sentChanges.isEmpty()) {
/* 1387 */         return ctxt;
/*      */       }
/* 1389 */       notifications = new LinkedList(this.sentChanges);
/*      */     }
/*      */     
/*      */ 
/* 1393 */     QueuedNotifications last = (QueuedNotifications)notifications.getLast();
/* 1394 */     for (QueuedNotifications ntfn : notifications) {
/* 1395 */       if ((ntfn.hasNotifications()) || (ntfn == last)) {
/* 1396 */         putQueuedNotifications(mbox, ntfn, ctxt, zsc);
/*      */       }
/*      */     }
/*      */     
/* 1400 */     return ctxt;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   private boolean encodingMatches(Element parent, Element newChild)
/*      */   {
/* 1413 */     return parent.getClass().equals(newChild.getClass());
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   protected void putQueuedNotifications(Mailbox mbox, QueuedNotifications ntfn, Element parent, ZimbraSoapContext zsc)
/*      */   {
/* 1420 */     Element eNotify = parent.addElement("notify");
/* 1421 */     if (ntfn.getSequence() > 0) {
/* 1422 */       eNotify.addAttribute("seq", ntfn.getSequence());
/*      */     }
/* 1424 */     OperationContext octxt = null;
/*      */     try {
/* 1426 */       octxt = DocumentHandler.getOperationContext(zsc, this);
/*      */     } catch (ServiceException e) {
/* 1428 */       ZimbraLog.session.warn("error fetching operation context for: " + zsc.getAuthtokenAccountId(), e);
/* 1429 */       return;
/*      */     }
/*      */     
/* 1432 */     boolean debug = ZimbraLog.session.isDebugEnabled();
/*      */     
/* 1434 */     PendingModifications pms = ntfn.mMailboxChanges;
/* 1435 */     RemoteNotifications rns = ntfn.mRemoteChanges;
/*      */     
/* 1437 */     Element eDeleted = eNotify.addUniqueElement("deleted");
/* 1438 */     StringBuilder deletedIds = new StringBuilder();
/* 1439 */     if ((pms != null) && (pms.deleted != null) && (pms.deleted.size() > 0)) {
/* 1440 */       for (PendingModifications.ModificationKey mkey : pms.deleted.keySet()) {
/* 1441 */         addDeletedNotification(mkey, deletedIds);
/*      */       }
/*      */     }
/* 1444 */     if ((rns != null) && (rns.deleted != null)) {
/* 1445 */       deletedIds.append(deletedIds.length() == 0 ? "" : ",").append(rns.deleted);
/*      */     }
/* 1447 */     boolean hasLocalCreates = (pms != null) && (pms.created != null) && (!pms.created.isEmpty());
/* 1448 */     boolean hasRemoteCreates = (rns != null) && (rns.created != null) && (!rns.created.isEmpty());
/* 1449 */     Element eCreated; if ((hasLocalCreates) || (hasRemoteCreates)) {
/* 1450 */       eCreated = eNotify.addUniqueElement("created");
/* 1451 */       if (hasLocalCreates) {
/* 1452 */         for (MailItem item : pms.created.values()) {
/* 1453 */           ItemIdFormatter ifmt = new ItemIdFormatter(this.mAuthenticatedAccountId, item.getMailbox(), false);
/*      */           try {
/* 1455 */             Element elem = ToXML.encodeItem(eCreated, ifmt, octxt, item, -4194305);
/*      */             
/* 1457 */             if (((item instanceof Mountpoint)) && (mbox == item.getMailbox())) {
/* 1458 */               Map<ItemId, Pair<Boolean, Element>> mountpoints = new HashMap(2);
/* 1459 */               expandLocalMountpoint(octxt, (Mountpoint)item, eCreated.getFactory(), mountpoints);
/* 1460 */               expandRemoteMountpoints(octxt, zsc, mountpoints);
/* 1461 */               transferMountpointContents(elem, octxt, mountpoints);
/*      */             }
/*      */           } catch (ServiceException e) {
/* 1464 */             ZimbraLog.session.warn("error encoding item " + item.getId(), e);
/* 1465 */             return;
/*      */           }
/*      */         }
/*      */         
/* 1469 */         if ((!eCreated.hasChildren()) && (debug)) {
/* 1470 */           ZimbraLog.session.debug("no serialied creates for item set: %s", new Object[] { pms.created.keySet() });
/*      */         }
/*      */       }
/* 1473 */       if (hasRemoteCreates) {
/* 1474 */         if (debug) {
/* 1475 */           ZimbraLog.session.debug("adding %d proxied creates", new Object[] { Integer.valueOf(rns.created.size()) });
/*      */         }
/* 1477 */         for (Element elt : rns.created) {
/* 1478 */           if (encodingMatches(parent, elt)) {
/* 1479 */             eCreated.addElement(elt.clone().detach());
/*      */           } else {
/* 1481 */             ZimbraLog.session.warn("unable to add remote notification due to mismatched SOAP protocol");
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */     
/* 1487 */     ItemIdFormatter ifmt = new ItemIdFormatter(zsc);
/* 1488 */     boolean hasLocalModifies = (pms != null) && (pms.modified != null) && (!pms.modified.isEmpty());
/* 1489 */     boolean hasRemoteModifies = (rns != null) && (rns.modified != null) && (!rns.modified.isEmpty());
/* 1490 */     Element eModified; if ((hasLocalModifies) || (hasRemoteModifies)) {
/* 1491 */       eModified = eNotify.addUniqueElement("modified");
/* 1492 */       if (hasLocalModifies) {
/* 1493 */         for (PendingModifications.Change chg : pms.modified.values()) {
/* 1494 */           if ((chg.why != 0) && ((chg.what instanceof MailItem))) {
/* 1495 */             MailItem item = (MailItem)chg.what;
/*      */             try
/*      */             {
/* 1498 */               Element elt = ToXML.encodeItem(eModified, ifmt, octxt, item, chg.why);
/* 1499 */               if (elt == null) {
/* 1500 */                 PendingModifications.ModificationKey mkey = new PendingModifications.ModificationKey(item);
/* 1501 */                 addDeletedNotification(mkey, deletedIds);
/* 1502 */                 if (debug) {
/* 1503 */                   ZimbraLog.session.debug("marking nonserialized item as a delete: %s", new Object[] { mkey });
/*      */                 }
/*      */               }
/*      */             } catch (ServiceException e) {
/* 1507 */               ZimbraLog.session.warn("error encoding item " + item.getId(), e);
/* 1508 */               return;
/*      */             }
/* 1510 */           } else if ((chg.why != 0) && ((chg.what instanceof Mailbox))) {
/* 1511 */             ToXML.encodeMailbox(eModified, octxt, (Mailbox)chg.what, chg.why);
/*      */           }
/*      */         }
/*      */         
/* 1515 */         if ((!eModified.hasChildren()) && (debug)) {
/* 1516 */           ZimbraLog.session.debug("no serialied modifies for item set: %s", new Object[] { pms.modified.keySet() });
/*      */         }
/*      */       }
/* 1519 */       if (hasRemoteModifies) {
/* 1520 */         if (debug) {
/* 1521 */           ZimbraLog.session.debug("adding %d proxied modifies", new Object[] { Integer.valueOf(rns.modified.size()) });
/*      */         }
/* 1523 */         for (Element elt : rns.modified) {
/* 1524 */           if (encodingMatches(parent, elt)) {
/* 1525 */             eModified.addElement(elt.clone().detach());
/*      */           } else {
/* 1527 */             ZimbraLog.session.warn("unable to add remote notification due to mismatched SOAP protocol");
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */     
/* 1533 */     if ((rns != null) && (rns.activities != null) && (!rns.activities.isEmpty())) {
/* 1534 */       for (Element elt : rns.activities) {
/* 1535 */         if (encodingMatches(parent, elt)) {
/* 1536 */           eNotify.addElement(elt.clone().detach());
/*      */         } else {
/* 1538 */           ZimbraLog.session.warn("unable to add remote notification due to mismatched SOAP protocol");
/*      */         }
/*      */       }
/*      */     }
/*      */     
/* 1543 */     putExtraNotifications(ntfn, eNotify, ifmt);
/*      */     
/* 1545 */     if ((deletedIds == null) || (deletedIds.length() == 0)) {
/* 1546 */       eDeleted.detach();
/*      */     } else {
/* 1548 */       eDeleted.addAttribute("id", deletedIds.toString());
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   private void putExtraNotifications(QueuedNotifications ntfn, Element eNotify, ItemIdFormatter ifmt)
/*      */   {
/* 1560 */     if ((ntfn.mExternalNotifications != null) && (ntfn.mExternalNotifications.size() > 0)) {
/* 1561 */       for (Session.ExternalEventNotification extra : ntfn.mExternalNotifications) {
/* 1562 */         extra.addElement(eNotify);
/*      */       }
/*      */     }
/*      */     
/*      */ 
/* 1567 */     if ((activityCb != null) && (ntfn.mMailboxChanges != null)) {
/*      */       try {
/* 1569 */         activityCb.putActivities(ntfn.mMailboxChanges, eNotify, ifmt);
/*      */       } catch (ServiceException e) {
/* 1571 */         ZimbraLog.soap.warn("logging activities", e);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static void setActivityCallback(ActivityCallback cb)
/*      */   {
/* 1583 */     activityCb = cb;
/*      */   }
/*      */   
/*      */   private void addDeletedNotification(PendingModifications.ModificationKey mkey, StringBuilder deletedIds) {
/* 1587 */     if (deletedIds.length() != 0) {
/* 1588 */       deletedIds.append(',');
/*      */     }
/*      */     
/* 1591 */     if (!mkey.getAccountId().equals(this.mAuthenticatedAccountId)) {
/* 1592 */       deletedIds.append(mkey.getAccountId()).append(':');
/*      */     }
/* 1594 */     deletedIds.append(mkey.getItemId());
/*      */   }
/*      */   
/*      */   public synchronized void clearCachedQueryResults()
/*      */   {
/*      */     try {
/* 1600 */       Closeables.closeQuietly(this.queryResults);
/*      */     } finally {
/* 1602 */       this.queryString = "";
/* 1603 */       this.groupBy = "";
/* 1604 */       this.sortBy = "";
/* 1605 */       this.queryResults = null;
/*      */     }
/*      */   }
/*      */   
/*      */   public synchronized void putQueryResults(String query, String groupBy, String sortBy, ZimbraQueryResults res) {
/* 1610 */     clearCachedQueryResults();
/* 1611 */     this.queryString = query;
/* 1612 */     this.groupBy = groupBy;
/* 1613 */     this.sortBy = sortBy;
/* 1614 */     this.queryResults = res;
/*      */   }
/*      */   
/*      */   public synchronized ZimbraQueryResults getQueryResults(String query, String groupBy, String sortBy) {
/* 1618 */     if ((this.queryString.equals(query)) && (this.groupBy.equals(groupBy)) && (this.sortBy.equals(sortBy))) {
/* 1619 */       return this.queryResults;
/*      */     }
/* 1621 */     return null;
/*      */   }
/*      */   
/*      */   public SoapProtocol getResponseProtocol()
/*      */   {
/* 1626 */     return this.responseProtocol;
/*      */   }
/*      */   
/*      */   public void cleanup()
/*      */   {
/* 1631 */     clearCachedQueryResults();
/*      */   }
/*      */   
/*      */   public static abstract interface ActivityCallback
/*      */   {
/*      */     public abstract void putActivities(PendingModifications paramPendingModifications, Element paramElement, ItemIdFormatter paramItemIdFormatter)
/*      */       throws ServiceException;
/*      */   }
/*      */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/session/SoapSession.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */